package com.lnj.community.filter;

import com.lnj.community.config.JwtConfig;
import com.lnj.community.dao.entity.User;
import com.lnj.community.service.UserService;
import com.lnj.community.utiles.CommunityConstant;
import com.lnj.community.utiles.JwtUtil;
import com.lnj.community.utiles.RedisKeyUtil;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtConfig jwtConfig;
    private final UserService userService;
    private final RedisTemplate redisTemplate;

    public JwtAuthenticationFilter(JwtConfig jwtConfig,
                                   UserService userService,
                                   RedisTemplate redisTemplate) {
        this.jwtConfig = jwtConfig;
        this.userService = userService;
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        // 1. 获取Token
        String token = getTokenFromRequest(request);

        if (token != null) {
            try {
                // 2. 验证Token
                if (redisTemplate.hasKey(RedisKeyUtil.getTokenKey(token))) {
                    User user = (User) redisTemplate.opsForValue().get(RedisKeyUtil.getTokenKey(token));
                    setAuthentication(user, request);
                } else {
                    Claims claims = JwtUtil.parseJWT(jwtConfig.getUserSecretKey(), token);
                    User user = userService.findUserById(Integer.valueOf(claims.get(CommunityConstant.USER_ID).toString()));
                    setAuthentication(user, request);
                }
            } catch (Exception e) {
                SecurityContextHolder.clearContext();
            }
        }

        filterChain.doFilter(request, response);
    }

    private void setAuthentication(User user, HttpServletRequest request) {
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                user,
                null,  // 密码设为null
                userService.getAuthorities(user.getId())
        );

        // 设置安全上下文
        SecurityContext context = SecurityContextHolder.createEmptyContext();
        context.setAuthentication(authentication);
        SecurityContextHolder.setContext(context);

        // 设置请求属性以便后续使用
        request.setAttribute("loginUser", user);
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("lnj_token".equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }
}